from flask import Blueprint, request, jsonify, current_app
from marshmallow import ValidationError
from sqlalchemy.exc import IntegrityError
from app.extensions import db
from app.models import User, UserSchema, LoginSchema, RegisterSchema
from . import api_bp

# 创建schema实例
user_schema = UserSchema()
login_schema = LoginSchema()
register_schema = RegisterSchema()

@api_bp.route('/auth/register', methods=['POST'])
def register():
    """用户注册"""
    try:
        # 验证请求数据
        data = register_schema.load(request.json)
    except ValidationError as err:
        return jsonify({
            'code': 400,
            'message': '数据验证失败',
            'errors': err.messages
        }), 400

    # 检查用户名是否已存在
    if User.query.filter_by(username=data['username']).first():
        return jsonify({
            'code': 400,
            'message': '用户名已存在'
        }), 400

    # 检查邮箱是否已存在
    if User.query.filter_by(email=data['email']).first():
        return jsonify({
            'code': 400,
            'message': '邮箱已被注册'
        }), 400

    try:
        # 创建新用户
        user = User(
            username=data['username'],
            email=data['email'],
            full_name=data.get('full_name', '')
        )
        user.set_password(data['password'])

        db.session.add(user)
        db.session.flush()  # 获取用户ID

        # 为新用户创建默认图表
        from app.models import Chart, Node, Relationship
        default_chart = Chart(
            user_id=user.id,
            name='我的第一个产业链图',
            description='这是您的默认产业链图，您可以在此基础上进行编辑',
            is_default=True,
            status='active'
        )
        db.session.add(default_chart)
        db.session.flush()  # 获取图表ID

        # 创建一些示例节点
        sample_nodes = [
            {'name': '原材料供应商', 'type': 'supplier', 'description': '提供基础原材料', 'position_x': 100, 'position_y': 200, 'color': '#E6A23C', 'size': 60},
            {'name': '制造商', 'type': 'manufacturer', 'description': '负责产品制造', 'position_x': 300, 'position_y': 200, 'color': '#409EFF', 'size': 70},
            {'name': '分销商', 'type': 'distributor', 'description': '产品分销渠道', 'position_x': 500, 'position_y': 200, 'color': '#67C23A', 'size': 65},
            {'name': '零售商', 'type': 'retailer', 'description': '终端销售', 'position_x': 700, 'position_y': 200, 'color': '#F56C6C', 'size': 55},
            {'name': '消费者', 'type': 'consumer', 'description': '最终消费者', 'position_x': 900, 'position_y': 200, 'color': '#909399', 'size': 50}
        ]

        node_ids = []
        for node_data in sample_nodes:
            node = Node(
                chart_id=default_chart.id,
                name=node_data['name'],
                type=node_data['type'],
                description=node_data['description'],
                position_x=node_data['position_x'],
                position_y=node_data['position_y'],
                color=node_data['color'],
                size=node_data['size'],
                status='active'
            )
            db.session.add(node)
            db.session.flush()
            node_ids.append(node.id)

        # 创建关系
        sample_relationships = [
            {'upstream_idx': 0, 'downstream_idx': 1, 'type': 'supply', 'label': '原材料供应', 'strength': 0.9},
            {'upstream_idx': 1, 'downstream_idx': 2, 'type': 'supply', 'label': '产品供应', 'strength': 0.85},
            {'upstream_idx': 2, 'downstream_idx': 3, 'type': 'distribute', 'label': '产品分销', 'strength': 0.8},
            {'upstream_idx': 3, 'downstream_idx': 4, 'type': 'retail', 'label': '零售销售', 'strength': 0.9}
        ]

        for rel_data in sample_relationships:
            relationship = Relationship(
                chart_id=default_chart.id,
                upstream_node_id=node_ids[rel_data['upstream_idx']],
                downstream_node_id=node_ids[rel_data['downstream_idx']],
                relationship_type=rel_data['type'],
                label=rel_data['label'],
                strength=rel_data['strength'],
                color='#67C23A',
                status='active'
            )
            db.session.add(relationship)

        db.session.commit()

        return jsonify({
            'code': 201,
            'message': '注册成功',
            'data': user.to_dict()
        }), 201

    except IntegrityError:
        db.session.rollback()
        return jsonify({
            'code': 400,
            'message': '用户名或邮箱已存在'
        }), 400
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Registration error: {str(e)}")
        return jsonify({
            'code': 500,
            'message': '注册失败，请稍后重试'
        }), 500

@api_bp.route('/auth/login', methods=['POST'])
def login():
    """用户登录"""
    try:
        # 验证请求数据
        data = login_schema.load(request.json)
    except ValidationError as err:
        return jsonify({
            'code': 400,
            'message': '数据验证失败',
            'errors': err.messages
        }), 400

    # 查找用户（支持用户名或邮箱登录）
    user = User.query.filter(
        (User.username == data['username']) | (User.email == data['username'])
    ).first()

    if not user or not user.check_password(data['password']):
        return jsonify({
            'code': 401,
            'message': '用户名或密码错误'
        }), 401

    if not user.is_active:
        return jsonify({
            'code': 403,
            'message': '账户已被禁用'
        }), 403

    try:
        # 生成JWT令牌
        token = user.generate_token(current_app.config['SECRET_KEY'])

        # 更新最后登录时间
        user.update_last_login()

        return jsonify({
            'code': 200,
            'message': '登录成功',
            'data': {
                'user': user.to_dict(),
                'token': token
            }
        })

    except Exception as e:
        current_app.logger.error(f"Login error: {str(e)}")
        return jsonify({
            'code': 500,
            'message': '登录失败，请稍后重试'
        }), 500

@api_bp.route('/auth/profile', methods=['GET'])
def get_profile():
    """获取用户资料"""
    # 从请求头获取token
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({
            'code': 401,
            'message': '未提供有效的认证令牌'
        }), 401

    token = auth_header.split(' ')[1]
    user = User.verify_token(token, current_app.config['SECRET_KEY'])

    if not user:
        return jsonify({
            'code': 401,
            'message': '无效或过期的令牌'
        }), 401

    return jsonify({
        'code': 200,
        'message': '获取成功',
        'data': user.to_dict()
    })

@api_bp.route('/auth/profile', methods=['PUT'])
def update_profile():
    """更新用户资料"""
    # 验证token
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({
            'code': 401,
            'message': '未提供有效的认证令牌'
        }), 401

    token = auth_header.split(' ')[1]
    user = User.verify_token(token, current_app.config['SECRET_KEY'])

    if not user:
        return jsonify({
            'code': 401,
            'message': '无效或过期的令牌'
        }), 401

    try:
        data = request.json

        # 更新允许的字段
        if 'full_name' in data:
            user.full_name = data['full_name']
        if 'avatar' in data:
            user.avatar = data['avatar']

        # 如果要更新邮箱，需要检查是否已存在
        if 'email' in data and data['email'] != user.email:
            existing_user = User.query.filter_by(email=data['email']).first()
            if existing_user:
                return jsonify({
                    'code': 400,
                    'message': '邮箱已被其他用户使用'
                }), 400
            user.email = data['email']

        db.session.commit()

        return jsonify({
            'code': 200,
            'message': '更新成功',
            'data': user.to_dict()
        })

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Profile update error: {str(e)}")
        return jsonify({
            'code': 500,
            'message': '更新失败，请稍后重试'
        }), 500

@api_bp.route('/auth/change-password', methods=['POST'])
def change_password():
    """修改密码"""
    # 验证token
    auth_header = request.headers.get('Authorization')
    if not auth_header or not auth_header.startswith('Bearer '):
        return jsonify({
            'code': 401,
            'message': '未提供有效的认证令牌'
        }), 401

    token = auth_header.split(' ')[1]
    user = User.verify_token(token, current_app.config['SECRET_KEY'])

    if not user:
        return jsonify({
            'code': 401,
            'message': '无效或过期的令牌'
        }), 401

    data = request.json
    current_password = data.get('current_password')
    new_password = data.get('new_password')

    if not current_password or not new_password:
        return jsonify({
            'code': 400,
            'message': '请提供当前密码和新密码'
        }), 400

    # 验证当前密码
    if not user.check_password(current_password):
        return jsonify({
            'code': 400,
            'message': '当前密码错误'
        }), 400

    try:
        # 设置新密码
        user.set_password(new_password)
        db.session.commit()

        return jsonify({
            'code': 200,
            'message': '密码修改成功'
        })

    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"Password change error: {str(e)}")
        return jsonify({
            'code': 500,
            'message': '密码修改失败，请稍后重试'
        }), 500

@api_bp.route('/auth/verify-token', methods=['POST'])
def verify_token():
    """验证令牌有效性"""
    data = request.json
    token = data.get('token')

    if not token:
        return jsonify({
            'code': 400,
            'message': '请提供令牌'
        }), 400

    user = User.verify_token(token, current_app.config['SECRET_KEY'])

    if user:
        return jsonify({
            'code': 200,
            'message': '令牌有效',
            'data': {
                'valid': True,
                'user': user.to_dict()
            }
        })
    else:
        return jsonify({
            'code': 401,
            'message': '无效或过期的令牌',
            'data': {
                'valid': False
            }
        }), 401